package com.changhong.framework.sdfs.namenode.server.nio;

import com.changhong.framework.sdfs.namenode.server.builder.NameNodeBuilder;
import com.changhong.framework.sdfs.namenode.server.config.NameNodeConfig;
import com.changhong.framework.sdfs.namenode.server.constant.MemoryBufferType;
import com.changhong.framework.sdfs.namenode.server.context.NameNodeContext;

/**
 * @author Summer
 */
public class DoubleFlushManager {

    private MemoryBuffer currentBuffer=new MemoryBuffer();
    private MemoryBuffer fileFlushBuffer=new MemoryBuffer();
    private Long startId=1L;
    private Long endId=0L;
    private final NameNodeConfig nameNodeConfig;
    private final NameNodeContext nameNodeContext;

    public DoubleFlushManager(){
        this.nameNodeContext=NameNodeBuilder.getInstance(NameNodeContext.class);
        this.nameNodeConfig= NameNodeBuilder.getInstance(NameNodeConfig.class);;
    }


    public void writeLog(EditLog log) throws Exception {
        endId=log.getTxId();
        currentBuffer.write(log);
    }

    /**
     * 判断一下当前的缓冲区是否写满了需要刷到磁盘上去
     * @return
     */
    public boolean shouldSyncToDisk() {
        if(currentBuffer.getCurrentBufferSize() >= MemoryBufferType.MEMORY_BUFFER_SIZE_LIMIT) {
            return true;
        }
        return false;
    }

    /**
     * 交换两块缓冲区，为了同步内存数据到磁盘做准备
     */
    public void setReadyToSync() {
        MemoryBuffer tmp = currentBuffer;
        currentBuffer = fileFlushBuffer;
        fileFlushBuffer = tmp;
    }

    /**
     * 获取当前正在写的缓存内存块数据
     * @return 当前缓存的内存数据区域对象
     */
    public MemoryBuffer getCurrentBuffer(){
        return currentBuffer;
    }

    /**
     * 将syncBuffer缓冲区中的数据刷入磁盘中
     */
    public void flush() throws Exception {
        FileFlusher.flushDish(fileFlushBuffer.getBufferData(),generalDiskFileName());
        //刷盘就保存当前的数据到name node上下文中
        nameNodeContext.addStartEndOperationIndex(startId+"-"+endId,startId,endId);
        fileFlushBuffer.clear();
        startId=endId+1;
    }

    public String generalDiskFileName(){
         return nameNodeConfig.getFlushDiskPath()+"editlog"+startId+"-"+endId+".log";
    }

}
